package com.cskaoyan.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class CustomAspect {

    //pointcut
    /**
     * 方法名是作为id来进行使用
     * @Poincut的value属性写切入点表达式
     */
    @Pointcut("execution(* com..service..*(..))")
    //@Pointcut("@annotation()")
    public void servicePointcut() {
    }

    //通知方法名可以自定义
    @Before("execution(* com..service..*(..))") //直接写切入点表达式 👉 直接使用value属性
    public void before(JoinPoint joinPoint) {
        System.out.println("正道的光");
        //代理对象
        Object aThis = joinPoint.getThis();
        System.out.println(aThis);
        //委托类（目标类）对象
        Object target = joinPoint.getTarget();
        System.out.println(target);

        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        System.out.println(name);
        if (name.contains("login") || name.contains("logout")) {

        }

        Object[] args = joinPoint.getArgs();
        System.out.println(Arrays.asList(args));
    }

    @After("servicePointcut()") //引入切入点id 👉 引用的@Pointcut注解对应的方法名
    public void after(){
        System.out.println("照在大地上");
    }
    @Around("servicePointcut()")
    //可以对形参做修饰
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if ("sayHello".equals(joinPoint.getSignature().getName())) {
            args[1] = "张*玉";
        }
        Object proceed = joinPoint.proceed(args);
        return proceed;
    }

    //after-returning通知
    //在委托类方法执行return之后执行 → 拿到委托类方法的执行结果
    //使用Object来接收委托类方法的执行结果
    @AfterReturning(value = "servicePointcut()",returning = "result")
    public void afterReturning(Object result) {
        System.out.println("afterReturning通知接收到的委托类方法的执行结果：" + result);
    }

    //after-throwing通知：委托类方法（Around通知）抛出异常的时候，会执行到这个通知
    //可以接收到异常对象：Exception、Throwable
    @AfterThrowing(value = "servicePointcut()",throwing = "exception")
    public void afterThrowing(Exception exception) {
        System.out.println("抛出异常：" + exception.getMessage());
    }
}
